package com.anuo.app.modules.user.service;

import com.anuo.app.common.entity.DeviceType;
import com.anuo.app.common.entity.LocationFilter;
import com.anuo.app.common.globalhandle.AppException;
import com.anuo.app.common.globalhandle.GlobalConfig;
import com.anuo.app.common.persistence.PageData;
import com.anuo.app.common.persistence.RedisUtils;
import com.anuo.app.common.security.SecurityUtil;
import com.anuo.app.common.utils.NetUtil;
import com.anuo.app.common.utils.IdUtil;
import com.anuo.app.common.utils.JsonUtil;
import com.anuo.app.common.utils.StringUtil;
import com.anuo.app.modules.coach.entity.Coach;
import com.anuo.app.modules.system.service.SystemService;
import com.anuo.app.modules.user.dao.UserDao;
import com.anuo.app.modules.system.entity.*;
import com.anuo.app.modules.user.entity.UserAccount;
import com.anuo.app.modules.user.entity.UserFilter;
import com.anuo.app.modules.user.entity.UserLimit;
import com.anuo.app.modules.user.entity.WeiXinUserInfo;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;

@Service
@Transactional(readOnly = true)
public class UserService {
    @Autowired
    UserDao userDao;
    @Autowired
    SystemService systemService;

    @Transactional(readOnly = false)
    public void registerUser(UserAccount userAccount) {
        //设置密码等
        userAccount.preInsert();
        String userId = userAccount.getId();
        String hashedPassword = SecurityUtil.hashPassword(userAccount.getUser_password());
        userAccount.setUser_password(hashedPassword);
        userAccount.setPay_no_pwd_amount(0);
        userAccount.setCardid("");
        userDao.registerUser(userAccount);

        //设置默认权限
        UserLimit userLimit = new UserLimit();
        userLimit.preInsert();
        userLimit.setUserid(userId);
        userLimit.setIs_activity(true);
        userLimit.setIs_club(true);
        userDao.insertUserLimit(userLimit);
    }

    @Transactional(readOnly = false)
    public void addUser(UserAccount userAccount) {
        //设置密码等
        userAccount.preInsert();
        userAccount.setPay_no_pwd_amount(0);
        userAccount.setCardid("");
        userDao.registerUser(userAccount);

        //设置默认权限
        UserLimit userLimit = new UserLimit();
        userLimit.preInsert();
        userLimit.setUserid(userAccount.getId());
        userLimit.setIs_activity(true);
        userLimit.setIs_club(true);
        userDao.insertUserLimit(userLimit);
    }

    @Transactional(readOnly = true)
    public boolean isExistUserByMobile(UserAccount userAccount) {
        return userDao.isExistUser(userAccount);
    }

    @Transactional(readOnly = true)
    public boolean isExistUserById(String id) {
        UserAccount userAccount = new UserAccount();
        userAccount.setId(id);
        return userDao.isExistUser(userAccount);

    }


    @Transactional(readOnly = true)
    public boolean isHaveNewVerison(String deviceVersion, String deviceType) {
        Appversion appversion = systemService.getAppversion();
        boolean result;
        switch (deviceType) {
            case DeviceType.ANDROID:
                if (appversion.getAndroid_number() != deviceVersion) {
                    result = true;
                } else {
                    result = false;
                }
                break;
            case DeviceType.IPHONE:
                if (appversion.getIos_number() != deviceVersion) {
                    result = true;
                } else {
                    result = false;
                }
                break;
            default:
                result = false;
        }
        return result;

    }


    @Transactional(readOnly = false)
    public String validUser(String password, String mobile, boolean isPasswordDirectCompare) {
        UserFilter userFilter = new UserFilter();
        userFilter.setMobile(mobile);
        UserAccount userAccount = userDao.getUser(userFilter);
        //验证密码
        boolean passwordIsValid = false;
        if (!isPasswordDirectCompare) {
            //anuoapp 库的密码默认是 123456
            passwordIsValid = SecurityUtil.authenticatePassword(password, userAccount.getUser_password());
        } else {
            //微信,qq等三方登陆
            passwordIsValid = password.equals(userAccount.getUser_password());
        }

        if (passwordIsValid) {
            String token = IdUtil.getUUID();
            //验证通过添加到缓存(用户量起来了分布式用redis)
            //saveTokenToRedis(userAccount, token);
            //缓存到数据库(前期单机用数据库)
            saveTokenToDB(userAccount, token);
            return token;

        } else {
            return "";
        }

    }


    @Transactional(readOnly = true)
    public void saveTokenToRedis(UserAccount userAccount, String token) {
        userAccount.setPay_password("");
        userAccount.setUser_password("");
        String userJson = JsonUtil.toJson(userAccount);
        RedisUtils.setString(token, userJson);
    }


    @Transactional(readOnly = true)
    public void saveTokenToDB(UserAccount userAccount, String token) {
        Onlineuser onlineuser = new Onlineuser();
        onlineuser.preInsert();
        onlineuser.setUserid(userAccount.getId());
        onlineuser.setToken(token);
        userDao.deleteOnlineUser(onlineuser);
        userDao.insertOnlineUser(onlineuser);
    }


    @Transactional(readOnly = false)
    public LocationFilter getCurrentLocationRectangle(LocationFilter locationFilter) {
        LocationFilter locationResult = userDao.getCurrentLocationRectangle(locationFilter);
        return locationResult;
    }

    @Transactional(readOnly = false)
    public LocationFilter getCurrentLocationRectangleDouble(LocationFilter locationFilter) {
        LocationFilter locationResult = userDao.getCurrentLocationRectangleDouble(locationFilter);
        return locationResult;
    }

    @Transactional(readOnly = false)
    public void saveUserlimit(UserLimit userLimit) {
        boolean isExistsUserlimit = userDao.isExistUserLimit(userLimit);
        if (isExistsUserlimit) {
            userDao.updateUserLimit(userLimit);
        } else {
            userLimit.preInsert();
            userDao.insertUserLimit(userLimit);
        }
    }

    @Transactional(readOnly = true)
    public UserLimit getUserLimit(UserFilter userFilter) {
        return userDao.getUserLimit(userFilter);
    }

    @Transactional(readOnly = true)
    public boolean isExistToken(String token) {
        return userDao.isExistToken(token);
    }


    /**
     * 退出登录
     *
     * @param userAccount
     */
    @Transactional(readOnly = false)
    public void logout(UserAccount userAccount) {
        userDao.logout(userAccount);
    }

    @Transactional(readOnly = false)
    public void updateUserAccount(UserAccount userAccount) {
        userDao.updateUserAccount(userAccount);
    }

    @Transactional(readOnly = true)
    public UserAccount getUser(UserFilter userFilter) {
        return userDao.getUser(userFilter);
    }

    public UserAccount getUserById(String userId) {
        UserFilter userFilter = new UserFilter();
        userFilter.setUserid(userId);
        return userDao.getUser(userFilter);
    }

    public UserAccount getUserByMobile(String mobile) {
        UserFilter userFilter = new UserFilter();
        userFilter.setMobile(mobile);
        return userDao.getUser(userFilter);
    }


    @Transactional(readOnly = false)
    public void updateMobile(UserAccount userAccount) {
        //判断验证码是否正确
        systemService.checkMobileCode(userAccount.getMobile(),userAccount.getMobile_code());
        //判断此手机号是不是已经被其他人用了
        UserFilter userFilter = new UserFilter();
        userFilter.setUserid(userAccount.getId());
        userFilter.setMobile(userAccount.getMobile());
        UserAccount userAccount_db = userDao.getMobileExceptMe(userFilter);
        if (userAccount_db != null) {
            String msg = MessageFormat.format("此手机号已经和昵称为[{0}]绑定,请先解除绑定"
                    , userAccount_db.getCard_name());
            throw new AppException(msg);
        }
        //修改手机号
        userDao.updateMobile(userAccount);
    }

    @Transactional(readOnly = false)
    public void updatePassword(UserAccount userAccount) {
        //判断原密码是否正确
        UserAccount userAccount_db = getUserById(userAccount.getId());
        if (!SecurityUtil.authenticatePassword(userAccount.getOld_password(), userAccount_db.getUser_password())) {
            throw new AppException("原密码不正确, 请重新输入");
        }

        //修改成新密码
        userAccount.setUser_password(SecurityUtil.hashPassword(userAccount.getNew_password()));
        userDao.updateUserPassword(userAccount);
    }

    @Transactional(readOnly = false)
    public void resetPassword(UserAccount userAccount) {
        //判断验证码是否正确
        systemService.checkMobileCode(userAccount.getMobile(),userAccount.getMobile_code());
        //修改成新密码
        userAccount.setUser_password(SecurityUtil.hashPassword(userAccount.getNew_password()));
        userDao.updateUserPassword(userAccount);
    }

    /**
     * 获取微信用户的个人信息
     *
     * @param code
     * @return
     */
    public WeiXinUserInfo getWeiXinUserInfo(String code) {
        String appid = GlobalConfig.getConfig("WeXin.APP_ID");
        String secret = GlobalConfig.getConfig("WeXin.Secret");
        String baseUrl = "https://api.weixin.qq.com/sns";
        //先获取access_token
        String urlParam = "/oauth2/access_token?appid=" + appid + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";
        String url = baseUrl + urlParam;
        WeiXinUserInfo weiXinUserInfo = new WeiXinUserInfo();
        String result = NetUtil.sendGet(url);
        if (result.contains("errmsg")) {
            throw new AppException("调用微信获取token接口失败,原因:" + result);
        }
        weiXinUserInfo = JsonUtil.fromJson(result, new TypeReference<WeiXinUserInfo>() {
        });

        //在获取微信用户信息
        urlParam = "/userinfo?access_token=" + weiXinUserInfo.getAccess_token() + "&openid=" + weiXinUserInfo.getOpenid();
        url = baseUrl + urlParam;

        result = NetUtil.sendGet(url);
        if (result.contains("errmsg")) {
            throw new AppException("调用微信获取用户信息接口失败,原因:" + result);
        }
        weiXinUserInfo = JsonUtil.fromJson(result, new TypeReference<WeiXinUserInfo>() {
        });
        return weiXinUserInfo;
    }

    @Transactional(readOnly = false)
    public void bindWeiXin(UserAccount userAccount) {
        userDao.bindWeiXin(userAccount);
    }

    @Transactional(readOnly = false)
    public void bindQQ(UserAccount userAccount) {
        userDao.bindQQ(userAccount);
    }

    @Transactional(readOnly = false)
    public void unbindWeiXin(UserAccount userAccount) {
        userDao.unbindWeiXin(userAccount);
    }

    @Transactional(readOnly = true)
    public PageData<UserAccount> getAllUserList(UserFilter userFilter) {
        PageData<UserAccount> pageData = new PageData<>();
        //设置搜索字段(只能按昵称和手机号来搜索)
        if (StringUtil.isNotEmpty(userFilter.getKeywords())) {
            if (StringUtil.isNumeric(userFilter.getKeywords())) {
                userFilter.setMobile(userFilter.getKeywords());
            }
            else {
                userFilter.setPet_name(userFilter.getKeywords());
            }
        }

        //获取分页数据
        PageData.setTotalRow(pageData, userFilter, () -> userDao.getAllUserListCount(userFilter));
        PageData.setEntities(pageData, userDao.getAllUserList(userFilter));
        return pageData;
    }

    @Transactional(readOnly = true)
    public PageData<UserAccount> getCoachList(UserFilter userFilter) {
        PageData<UserAccount> pageData = new PageData<>();
        //设置搜索字段(只能按姓名来搜索,教练模块是个正式业务,所用姓名来查找教练最好)
        if (StringUtil.isNotEmpty(userFilter.getKeywords())) {
                userFilter.setCard_name(userFilter.getKeywords());
        }

        //获取分页数据
        PageData.setTotalRow(pageData, userFilter, () -> userDao.getCoachListCount(userFilter));
        PageData.setEntities(pageData, userDao.getCoachList(userFilter));
        return pageData;
    }

    /**
     * 查询普通用户列表(不包含教练)
     * @param userFilter
     * @return
     */
    @Transactional(readOnly = true)
    public PageData<UserAccount> getGeneralUserList(UserFilter userFilter) {
        PageData<UserAccount> pageData = new PageData<>();
        //设置搜索字段(只能按昵称和手机号来搜索)
        if (StringUtil.isNotEmpty(userFilter.getKeywords())) {
            if (StringUtil.isNumeric(userFilter.getKeywords())) {
                userFilter.setMobile(userFilter.getKeywords());
            }
            else {
                userFilter.setPet_name(userFilter.getKeywords());
            }
        }

        //获取分页数据
        PageData.setTotalRow(pageData, userFilter, () -> userDao.getGeneralUserListCount(userFilter));
        PageData.setEntities(pageData, userDao.getGeneralUserList(userFilter));
        return pageData;
    }

    @Transactional(readOnly = true)
    public PageData getUserNearbyAreaList(UserFilter userFilter) {
        //获取附近的矩形范围
        LocationFilter locationRectangle = getCurrentLocationRectangle(userFilter);
        userFilter.setLatitudeMax(locationRectangle.getLatitudeMax());
        userFilter.setLatitudeMin(locationRectangle.getLatitudeMin());
        userFilter.setLongitudeMax(locationRectangle.getLongitudeMax());
        userFilter.setLongitudeMin(locationRectangle.getLongitudeMin());
        PageData<Coach> pageData = new PageData<>();
        //获取分页数据
        PageData.setTotalRow(pageData, userFilter, () -> userDao.getUserNearbyAreaListCount(userFilter));
        PageData.setEntities(pageData, userDao.getUserNearbyAreaList(userFilter));
        return pageData;
    }



}

